// GTY


#include "Actor/AuraEffectActor.h"

#include "AbilitySystemBlueprintLibrary.h"
#include "AbilitySystemComponent.h"


AAuraEffectActor::AAuraEffectActor()
{
	PrimaryActorTick.bCanEverTick = false;

	SetRootComponent(CreateDefaultSubobject<USceneComponent>("SceneRoot"));

}



void AAuraEffectActor::BeginPlay()
{
	Super::BeginPlay();

}

void AAuraEffectActor::ApplyEffectToTarget(AActor* TargetActor, TSubclassOf<UGameplayEffect> GameplayEffectClass)
{
	if ( TargetActor->ActorHasTag(FName("Enemy")) && !bApplyEffectsToEnemies) { return; }
	UAbilitySystemComponent* TargetASC = UAbilitySystemBlueprintLibrary::GetAbilitySystemComponent(TargetActor);//目标对象 Target 中获取其关联的 UAbilitySystemComponent 组件
	if (TargetASC == nullptr){ return; }
	check(GameplayEffectClass);
	
	FGameplayEffectContextHandle EffectContextHandle = TargetASC->MakeEffectContext();
	//创建一个效果上下文

	EffectContextHandle.AddSourceObject(this);
	//并添加当前对象作为源对象
	
	const FGameplayEffectSpecHandle EffectSpecHandle = TargetASC->MakeOutgoingSpec(GameplayEffectClass, ActorLevel, EffectContextHandle);
	//创建一个效果规范。
	/*
	* 创建游戏效果规范句柄：调用 MakeOutgoingSpec 方法创建一个 FGameplayEffectSpecHandle。
	* 指定目标角色的能力系统组件：传入 TargetASC 作为目标角色的能力系统组件。
	* 应用游戏效果类：传入 GameplayEffectClass 指定要应用的游戏效果类。
	* 设置游戏效果强度为1.0：传入 1.f 设置游戏效果的强度为 1.0。
	* 传递上下文句柄：传入 EffectContextHandle 作为上下文句柄。
	*/
	
	const FActiveGameplayEffectHandle ActiveEffectHandle = TargetASC->ApplyGameplayEffectSpecToSelf(*EffectSpecHandle.Data.Get());
	//将效果应用到目标对象自身。

	const bool bIsInfinite = EffectSpecHandle.Data.Get()->Def.Get()->DurationPolicy == EGameplayEffectDurationType::Infinite;
	if (bIsInfinite && InfiniteEffectRemovalPolicy == EEffectRemovalPolicy::RemoveOnEndOverlap)
	{
		//将效果句柄添加到哈希表中，以跟踪效果
		ActiveEffectHandles.Add(ActiveEffectHandle,TargetASC);
	}
	else if(bDestroyOnEffectApplication) //如果设置了应用时删除，除了Infinite的都会自动删除
	{
		Destroy();
	}
	
	
}	
void AAuraEffectActor::OnOverlap(AActor* TargetActor)
{
	if ( TargetActor->ActorHasTag(FName("Enemy")) && !bApplyEffectsToEnemies) { return; }
	if (InstantEffectApplicationPolicy == EEffectApplicationPolicy::ApplyOnOverlap)
	{
		ApplyEffectToTarget(TargetActor, InstantGameplayEffectClass);
	}
	if (DurationEffectApplicationPolicy == EEffectApplicationPolicy::ApplyOnOverlap)
	{
		ApplyEffectToTarget(TargetActor, DurationGameplayEffectClass);
	}
	if (InfiniteEffectApplicationPolicy == EEffectApplicationPolicy::ApplyOnOverlap)
	{
		ApplyEffectToTarget(TargetActor, InfiniteGameplayEffectClass);
	}
}

void AAuraEffectActor::OnEndOverlap(AActor* TargetActor)
{
	if ( TargetActor->ActorHasTag(FName("Enemy")) && !bApplyEffectsToEnemies) { return; }
	if (InstantEffectApplicationPolicy == EEffectApplicationPolicy::ApplyOnEndOverlap)
	{
		ApplyEffectToTarget(TargetActor, InstantGameplayEffectClass);
	}
	if (DurationEffectApplicationPolicy == EEffectApplicationPolicy::ApplyOnEndOverlap)
	{
		ApplyEffectToTarget(TargetActor, DurationGameplayEffectClass);
	}
	if (InfiniteEffectApplicationPolicy == EEffectApplicationPolicy::ApplyOnEndOverlap)
	{
		ApplyEffectToTarget(TargetActor, InfiniteGameplayEffectClass);
	}
	if (InfiniteEffectRemovalPolicy == EEffectRemovalPolicy::RemoveOnEndOverlap)
	{
		UAbilitySystemComponent* TargetASC = UAbilitySystemBlueprintLibrary::GetAbilitySystemComponent(TargetActor);
		if (!IsValid(TargetASC)){ return; }

		/*创建数组存放被移除的游戏效果
		 * 遍历哈希表中的所有元素，移除效果，并将移除的效果添加到数组中。
		 * 遍历数组，匹配，移除哈希表中的元素。
		 */
		TArray<FActiveGameplayEffectHandle> HandlesToRemove;
		for (TTuple<FActiveGameplayEffectHandle,UAbilitySystemComponent*> HandlePair: ActiveEffectHandles)
		{
			if (TargetASC == HandlePair.Value)
			{
				//移除效果
				TargetASC->RemoveActiveGameplayEffect(HandlePair.Key,1);//只移除一个堆栈，在多堆栈重叠到少时不会移除所有
				
				HandlesToRemove.Add(HandlePair.Key);
			}
		}
		for (FActiveGameplayEffectHandle Handle: HandlesToRemove)
		{
			ActiveEffectHandles.FindAndRemoveChecked(Handle);
		}
	}
}



